<template>
    <div class="box box-body" v-loading="loading" style="width: 100%">
        <div v-if="props.searchbar">
            <el-input v-model="filterText" :size="props.size"
                      style="width: 100%"
                      placeholder="模糊搜索" clearable>
                <template #append><i class="fa fa-fw fa-search"></i></template>
            </el-input>
        </div>
        <el-tree ref="treeRef" node-key="id" :data="tree" :default-checked-keys="valueModel"
                 :filter-node-method="filterNode" @check="onNodeChecked"
                 accordion show-checkbox check-on-click-node default-expand-all
                 :expand-on-click-node="false">
        </el-tree>
    </div>
</template>

<script setup lang="ts">
import {ref, watch, onMounted} from 'vue';
import Asserts from "@/lang/core/asserts";
import Bamboo, {TreeMapper} from "@/lang/bamboo/index";
import TreeNode from "@/lang/bamboo/tree-node";
import type {TreeInstance} from 'element-plus'
import {useFilterText, useTree} from "@/widget/use/use-tree";

/**
 * 树形选择器
 */
interface Props {
    /** model-value */
    modelValue: number[] | string[]
    /** 组件大小 */
    size?: string
    /** 输入框的占位文字提示 */
    placeholder?: string

    /** 数据映射 **/
    mapper?: TreeMapper
    /** 启用搜索栏 **/
    searchbar?: boolean

    /** 数据字典配置 */
    options: TreeNode[]
    /** 异步查询参数 */
    where?: Record<string, any>
    /** 异步获取数结构数据 */
    provider?: (params) => Promise<TreeNode[]>
}

// 使用 withDefaults 设置默认值
const props = withDefaults(defineProps<Props>(), {
    size: 'default',
    placeholder: '',
    mapper: () => Bamboo.mapper_default,
    searchbar: true
})

const emit = defineEmits(['update:modelValue', 'change']);

// 值模型，内部实际在用的绑定数据
const valueModel = ref([]);

// References
const treeRef = ref<TreeInstance>()

// 使用树
const {tree, loading} = useTree(props);

// 使用过滤
const {filterText, filterNode, filterMethod} = useFilterText(treeRef);

// Watchers
watch(() => props.modelValue, (val) => {
    if (val !== valueModel.value) {
        valueModel.value = val;
        treeRef.value.setCheckedKeys(val);
    }
});

/**
 * 节点选中事件
 *
 * @param node 当前节点
 * @param checked 是否选中
 * @param indeterminate -
 */
const onNodeChecked = (node, checked, indeterminate) => {
    const nodes = treeRef.value.getCheckedNodes();
    // change 事件返回节点列表
    emit('change', nodes);
    // v-model 返回 id 列表
    emit('update:modelValue', Bamboo.getIds(nodes));
};

onMounted(() => {
    // 设置选中的节点
    treeRef.value.setCheckedKeys(props.modelValue);
})
</script>